#ifndef __PLAYER_BONUS_H__
#define __PLAYER_BONUS_H__

//#include "player.h"
#include "frame.h"

class FrameBonus
{
public:
    FrameBonus(Frame* f)
    : _frame(f),
      _isActive(true)
    {
    }
    
    virtual ~FrameBonus() = 0;

    void cast()
    {
        if (_isActive)
        {
            doCast();
        }
    }
    
    bool isActive() const
    {
        return _isActive;
    }
    
protected:
    virtual void doCast() = 0;
    
protected:
    Frame* _frame;
    bool   _isActive;
};

inline FrameBonus::~FrameBonus()
{
}

class ScoresMultiplier : public FrameBonus
{
public:
    ScoresMultiplier(Frame* f, int pinsKnocked, int fireTimes)
    : FrameBonus(f),
      _pinsKnocked(pinsKnocked),
      _usedTimes(0),
      _fireTimes(fireTimes)
    {
    }
    
    virtual void doCast()
    {
        if (_usedTimes < _fireTimes)
        {
            _frame->addScores(_pinsKnocked);
            ++_usedTimes;
            if (_usedTimes == _fireTimes)
            {
                _isActive = false;
            }
        }
    }
    
private:
    int _pinsKnocked;
    int _usedTimes;
    int _fireTimes;
};

class SpareBonus : public ScoresMultiplier
{
public:
    SpareBonus(Frame* f, int pinsKnocked)
    : ScoresMultiplier(f, pinsKnocked, 1)
    {
    }
    
    virtual ~SpareBonus()
    {
    }

};

class StrikeBonus : public ScoresMultiplier
{
public:
    StrikeBonus(Frame* f, int pinsKnocked)
    : ScoresMultiplier(f, pinsKnocked, 2)
    {
    }
    
    virtual ~StrikeBonus()
    {
    }
};


class FrameBonusFactory
{
public:
    static std::unique_ptr<FrameBonus> create(Frame::Bonus bonus, Frame* frame, int pinsKnocked)
    {
        switch (bonus)
        {
        case Frame::Bonus::STRIKE:
            return std::unique_ptr<StrikeBonus>(new StrikeBonus(frame, pinsKnocked));
        case Frame::Bonus::SPARE:
            return std::unique_ptr<SpareBonus>(new SpareBonus(frame, pinsKnocked));
        default:
            return std::unique_ptr<FrameBonus>();
        }
    }
};

#endif 